﻿/***********************************************************
float3 lightVec = _WorldSpaceLightPos0.xyz - i.worldPos;
float attenuation = 1 / (1 + dot(lightVec, lightVec));

#ifdef POINT
uniform sampler2D _LightTexture0;
uniform unityShadowCoord4x4 unity_WorldToLight;

#define UNITY_LIGHT_ATTENUATION(destName, input, worldPos) \
	unityShadowCoord3 lightCoord = \
		mul(unity_WorldToLight, unityShadowCoord4(worldPos, 1)).xyz; \
	fixed destName = \
		(tex2D(_LightTexture0, dot(liggtCoord, lightCoord).rr). \
		UNITY_ATTEN_CHANNEL * SHADOW_ATTENUATION(input));
#endif
***********************************************************/

/***********************************************************
float3 lightPos = float3(
	unity_4LightPosX0.x, unity_4LightPosY0.x, unity_4LightPosZ0.x
);
float3 lightVec = lightPos - i.worldPos;
float3 lightDir = normalize(lightVec);
float3 ndotl = DotClamped(i.normal, lightDir);
float attenuation = 1 / (1 + dot(lightVec, lightVec) * unity_4LightAtten0);
i.vertexLightColor = unity_LightColor[0].rgb * ndotl * attenuation;

i.vertexLightColor = Shade4PointLights(
	unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
	unity_LightColor[0].rgb, unity_LightColor[1].rgb,
	unity_LightColor[2].rgb, unity_LightColor[3].rgb,
	unity_4LightAtten0, i.worldPos, i.normal
);
***********************************************************/

#if !defined(LIGHTING_LIB)
#define LIGHTING_LIB

#include "AutoLight.cginc"
#include "UnityPBSLighting.cginc"

float4 _Tint;
sampler2D _MainTex;
float4 _MainTex_ST;
float _Metallic;
float _Smoothness;

struct VertexData {
	float4 position : POSITION;
	float2 uv : TEXCOORD0;
	float3 normal : NORMAL;
};

struct Interpolators {
	float4 position : POSITION;
	float2 uv : TEXCOORD0;
	float3 normal : TEXCOORD1;
	float3 worldPos : TEXCOORD2;
	
	#if defined(VERTEXLIGHT_ON)
		float3 vertexLightColor : TEXCOORD3;
	#endif
};

void ComputeVertexLightColor(inout Interpolators i) {
	#if defined(VERTEXLIGHT_ON)
		i.vertexLightColor = Shade4PointLights(
			unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,
			unity_LightColor[0].rgb, unity_LightColor[1].rgb,
			unity_LightColor[2].rgb, unity_LightColor[3].rgb,
			unity_4LightAtten0, i.worldPos, i.normal
		);
	#endif
}

Interpolators MyVertexProgram(VertexData v) {
	Interpolators i;
	i.position = UnityObjectToClipPos(v.position);
	i.worldPos = mul(unity_ObjectToWorld, v.position);
	i.normal = UnityObjectToWorldNormal(v.normal);
	i.uv = TRANSFORM_TEX(v.uv, _MainTex);
	ComputeVertexLightColor(i);
	return i;
}

UnityLight CreateLight(Interpolators i) {
	UnityLight light; // 像素光
	
	#if defined(POINT) || defined(POINT_COOKIE) || defined(SPOT)
		light.dir = normalize(_WorldSpaceLightPos0.xyz - i.worldPos);
	#else
		light.dir = _WorldSpaceLightPos0.xyz;
	#endif
	
	UNITY_LIGHT_ATTENUATION(attenuation, 0, i.worldPos);
	light.color = _LightColor0.rgb * attenuation;
	light.ndotl = DotClamped(i.normal, light.dir);
	return light;
}

UnityIndirect CreateIndirectLight(Interpolators i) {
	UnityIndirect indirectLight;
	indirectLight.diffuse = 0;
	indirectLight.specular = 0;
	
	#if defined(VERTEXLIGHT_ON)
		indirectLight.diffuse = i.vertexLightColor; // 顶点光
	#endif
	
	#if defined(FORWARD_BASE_PASS)
		indirectLight.diffuse += max(0, ShadeSH9(float4(i.normal, 1))); // 球谐光
	#endif
	
	return indirectLight;
}

float4 MyFragmentProgram(Interpolators i) : SV_TARGET {
	i.normal = normalize(i.normal); // 误差很小，可以不调用，以提升性能
	
	float3 viewDir = normalize(_WorldSpaceCameraPos - i.worldPos);

	float3 albedo = tex2D(_MainTex, i.uv).rgb * _Tint.rgb;
	float3 specularTint;
	float oneMinusReflectivity;
	albedo *= DiffuseAndSpecularFromMetallic(
		albedo, _Metallic, specularTint, oneMinusReflectivity
	);
	
	return UNITY_BRDF_PBS(
		albedo, specularTint, oneMinusReflectivity, _Smoothness,
		i.normal, viewDir, CreateLight(i), CreateIndirectLight(i)
	);
}

#endif